#include <fstream>
#include"Map.h"

vector<Core> initCores(int width,int height,int length,double es,double is,double os) {
	vector<Core> cores;
	for (int l = 0; l < length; l++) {
		for (int h = 0; h < height; h++) {
			for (int w = 0; w < width; w++) {
				Core core(h, w,l,es,is,os);
				cores.push_back(core);
			}
		}
	}
	return cores;
}

Map::Map(int l, int h,int w,double es,double is,double os, int fraction,string powerPrefix) {
	width = w;
	height = h;
	length = l;
	cores = initCores(width,height,length,es,is,os);
	availableCores = height * width*length - fraction;
	ofstream flpFile(powerPrefix+".flp");
	ofstream powerFile(powerPrefix + ".ptrace");
	double hardh =0.002, hardw = 0.0015;
	for (int i = 0; i < l; i++) {
		for (int j = 0; j < h; j++) {
			for (int k = 0; k < w; k++) {
				flpFile << "unit_" << i<<"_" << j << "_" << k << "\t" << hardw << "\t" << hardh << "\t" << k*hardw << "\t" << j*hardh << endl;
				powerFile << "unit_" << i << "_" << j << "_" << k << "\t";
			}
		}
	}
	powerFile << endl;

	flpFile.close();
	powerFile.close();

}

int Map::getWidth() {
	return width;
}

int Map::getHeight() {
	return height;
}

int Map::getLength() {
	return length;
}

/*void Map::updateAvailableCores(int i) {
	availableCores += i;
	//showMap();
}*/

bool Map::turnOnCore(InvokedTask task, Vertex ver)
{
	if (!getSpecificCore(ver)->checkState()) {
		getSpecificCore(ver)->turnOn(task.getApplicationId(), task.getId());
		availableCores--;
		return true;
	}
	return false;
}

bool Map::turnOffCore(Vertex ver)
{
	if (getSpecificCore(ver)->checkState()) {
		getSpecificCore(ver)->turnOff();
		availableCores++;
		return true;
	}
	return false;
}

int Map::getAvailableCores() {
	return availableCores;
}

Core* Map::getSpecificCore(Vertex v) {
	int index = toIndex(v);
	return &(cores.at(index));
}

Core* Map::getSpecificCore(int index) {
	return &(cores.at(index));
}

int Map::toIndex(Vertex v) {
	return v.l*width*height + v.h*width + v.w;
}
Vertex Map::toVertex(int i) {
	int l = i / (width*height);
	int h = (i % (width*height)) / width;
	int w = (i % (width*height)) % width;
	return Vertex(l,h,w);
}

void Map::showMap() {
	//cout << endl;
	for(int k = 0; k < length; k++) {
		//cout << k << ":" << endl;
		for (int i = 0; i < height; i++) {
			for (int j = 0; j < width; j++) {
				Vertex temp(k, i, j);
				cout << cores.at(toIndex(temp)).getApplicationId() << " ";
			}
			//cout << endl;
		}
		//cout << endl;
	}
	
	//cout <<"availableCores:"<< availableCores << endl;
	//cout << endl;
}

void Map::savePower(string filePrefix) {
	ofstream powerTrace(filePrefix + ".ptrace",ios::app);
	for (int k = 0; k < length; k++) {
		//cout << k << ":" << endl;
		for (int i = 0; i < height; i++) {
			for (int j = 0; j < width; j++) {
				Vertex temp(k, i, j);
				if (cores.at(toIndex(temp)).checkState()) {
					powerTrace << 8 << "\t" ;
				}
				else {
					powerTrace << 0 << "\t";
				}
			}
			//cout << endl;
		}
		//cout << endl;
	}
	powerTrace << endl;
	powerTrace.close();
}
